package com.Akxymcp.hta.command;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

/**指令节点*/
public class ComPath {

	/**子节点列表*/
	Map<String,ComPath> subPath = new HashMap<String,ComPath>();
	/**值型子节点*/
	ValuePath subVpath;
	
	/**父节点*/
	ComPath supPath;
	
	/**名称*/
	String name;
	
	/**需求权限*/
	String perm;
	
	/**是否只允许游戏内执行*/
	boolean isInGame = false;
	
	/**是否要求必须是op*/
	boolean isOp = false;
	
	
	/**执行函数,未 被设定时默认调用父节点执行函数*/
	public ComFun comfun = (sd,values)->
	{
		if(supPath!=null)
		{
			return supPath.excute(sd, values);
		}
		return false;
	};
	
	
	/**输入错误的回调函数>当输入的子节点因为错误无法继续传递时的回调函数,
	 * 未被设定时默认调用此节点excute执行函数,
	 * 比如 此节点名为time,输入/time settt中set打错,默认则视为/time,
	 * */
	public ComFun falsefun = this::excute;

	
	/**创建节点>名称*/
	public ComPath(String name) 
	{
		this.name = name;
	}
	/**创建节点>名称,父节点*/
	public ComPath(String name,ComPath suppath) 
	{
		this.name = name;
		this.supPath = suppath;
		if(suppath!=null)
		suppath.getSubPath().put(name,this);
	}
	/**创建节点>名称,父节点,执行函数*/
	public ComPath(String name,ComPath suppath,ComFun function) 
	{
		this.name = name;
		this.supPath = suppath;
		if(suppath!=null)
		suppath.getSubPath().put(name,this);
		this.comfun = function;
	}
	
	/**添加子节点,子节点的父节点会被自动设置为此节点*/
	public ComPath addPath(ComPath path)
	{
		path.setSupPath(this);
		subPath.put(path.getName(),path);
		return this;
	}
	/**添加值型节点,若添加了值型子节点,则不建议再添加其他子节点*/
	public ComPath addValuePath(ValuePath path)
	{
		subVpath = path;
		path.setSupPath(this);
		return this;
	}
	
	/**输入所有参数,然后执行>执行者,参数(所有子节点)*/
	public boolean input(CommandSender sd,String[] args)
	{
		return input(sd,args,new ArrayList<String>());
	}
	
	/**输入所有参数,然后执行>执行者,参数,传递值(传递值会在传递时 记录所有 值型节点的值)*/
	public boolean input(CommandSender sd,String[] args,List<String> values)
	{
		if(!correct(sd))
			return false;
		
		
		
		if(args.length==0)
		{//参数为空>说明已经传递到最后>所以直接执行此节点
			return excute(sd, values);
		}
		
		
		//_以下将传递参数给子节点
		//_无子节点,直接结束
		if(subVpath==null&&subPath.isEmpty())
		return false;
		
		
		if(subVpath!=null)
		{//处理值型子节点
			
			if(subVpath.correct(sd))
			{
				if(subVpath.isValues())
				{
					values.addAll(new ArrayList<>(Arrays.asList(args)));
					return subVpath.input(sd,new String[0],values);
				}else
				{
					values.add(args[0]);
					//加入传递值
					args = Arrays.copyOfRange(args,1,args.length);
					//去除首位
					return subVpath.input(sd,args,values);
				}
			}
			
		}else
		for(String name:subPath.keySet())
		{//筛选符合要求的子节点,传递
			if(args[0].equals(name))
			{
				args = Arrays.copyOfRange(args,1,args.length);
				//去除首位
				ComPath path = subPath.get(name);
				if(path.correct(sd))
					return path.input(sd,args,values);
				else
					break;
			}
		}
		
		//筛选完毕,若执行到此处,说明该节点不存在输入的子节点(输入错误)如time settt
		//默认执行父节点的方法
		return falsefun.excute(sd,values);
		
	}
	
	/**检查权限和条件,执行指令,若执行者不合条件,则执行父级节点>执行者,传递值*/
	public boolean excute(CommandSender sd,List<String> values)
	{
		if(correct(sd))
		{
			return comfun.excute(sd, values);
		}else if(supPath!=null)
		{
			return supPath.excute(sd, values);
		}else
		{
			return false;
		}
	}

	/**检查权限和条件*/
	public boolean correct(CommandSender sd)
	{
		if(isInGame)
		if(!(sd instanceof Player))
		{
			return false;
		}
		
		if(perm!=null)
		if(!sd.hasPermission(perm))
		{//处理权限
			return false;
		}
		
		if(isOp)
		if(!sd.isOp()&&(sd instanceof Player))
		{
			return false;
		}
		return true;
	}
	
	/**判断权限,补全指令>执行者,需要补全的子节点*/
	public List<String> tabInput(CommandSender sd,String[] args)
	{
		if(args.length==0)
		{
			if(subVpath!=null)
			{//处理值型节点
				if(subVpath.correct(sd))
				return subVpath.complete(sd,null);
			}else
			{
				List<String> list = new ArrayList<String>();
				for (String name:subPath.keySet()) 
	            {
	                if(subPath.get(name).correct(sd))
	                {
	                    list.add(name);
	                }
				}
				return list;
			}
			
		}else
		if(args.length==1)
		{
			if(subVpath!=null)
			{//处理值型节点
				if(subVpath.correct(sd))
				return subVpath.complete(sd,args[0]);
			}else
			{
				List<String> list = new ArrayList<String>();
				for (String name:subPath.keySet()) 
	            {
	                if (name.toLowerCase().startsWith(args[0].toLowerCase()))
	                if(subPath.get(name).correct(sd))
	                {
	                    list.add(name);
	                }
				}
				return list;
			}
			
			
		}else if(args.length>1)
		{
			String[] args0 = Arrays.copyOfRange(args,1,args.length);
			//去除首位
			if(subVpath!=null)
			{//处理值型节点
				if(subVpath.correct(sd))
				{
					if(subVpath.isValues())
					{//停止传递直接提示
						return subVpath.complete(sd,args0[args0.length-1]);
					}else
					return subVpath.tabInput(sd,args0);
					//继续传递
				}
			}
			ComPath sub = subPath.get(args[0]);
			if(sub!=null)
			{
				if(sub.correct(sd))
				return sub.tabInput(sd, args0);
			}
		}
		
		return new ArrayList<String>();
	}
	
	
	/**获取子节点*/
	public Map<String, ComPath> getSubPath() {
		return subPath;
	}
	public void setSubPath(Map<String, ComPath> subPath) {
		this.subPath = subPath;
	}
	/**获取父节点*/
	public ComPath getSupPath() {
		return supPath;
	}
	public void setSupPath(ComPath supPath) {
		this.supPath = supPath;
	}
	/**获取名称*/
	public String getName() {
		return name;
	}
	public ComPath setName(String name) {
		this.name = name;
		return this;
	}
	
	public boolean isInGame() {
		return isInGame;
	}
	public ComPath setInGame(boolean isInGame) {
		this.isInGame = isInGame;
		return this;
	}
	/**获取执行函数>
	 * 
	 * */
	public ComFun getComfun() {
		return comfun;
	}
	public ComPath setComfun(ComFun comfun) {
		this.comfun = comfun;
		return this;
	}

	/**获取是否要求必须是op*/
	public boolean isOp() {
		return isOp;
	}
	public ComPath setOp(boolean isOp) {
		this.isOp = isOp;
		return this;
	}
	
	/**获取需求权限*/
	public String getPerm() {
		return perm;
	}
	public ComPath setPerm(String perm) {
		this.perm = perm;
		return this;
	}
	
	
	
}
